package com.dtp.core.notify.alarm;

import com.dtp.common.entity.AlarmInfo;
import com.dtp.common.em.NotifyItemEnum;
import com.dtp.core.thread.DtpExecutor;
import com.dtp.core.thread.ExecutorAdapter;
import lombok.val;
import lombok.var;
import org.apache.commons.lang3.tuple.ImmutableTriple;
import org.apache.commons.lang3.tuple.Triple;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

import static com.dtp.common.constant.DynamicTpConst.UNKNOWN;
import static com.dtp.common.em.NotifyItemEnum.*;

/**
 * 报警计数器（用来限制警告次数是否超过了阈值）
 *
 * @author yanhom
 * @since 1.0.4
 *
 * @remark muse
 **/
public class AlarmCounter {

    private static final String DEFAULT_COUNT_STR = UNKNOWN + " / " + UNKNOWN; // "--- / ---"
    private static final Map<String, AlarmInfo> ALARM_INFO_CACHE = new ConcurrentHashMap<>();

    private AlarmCounter() {}

    /** 初始化缓存——ALARM_INFO_CACHE */
    public static void init(String threadPoolName, String notifyItemType) {
        String key = buildKey(threadPoolName, notifyItemType);
        val alarmInfo = AlarmInfo.builder().notifyItem(NotifyItemEnum.of(notifyItemType)).build(); // 构建AlarmInfo实例对象
        ALARM_INFO_CACHE.putIfAbsent(key, alarmInfo); // 进行缓存
    }

    /** 获得缓存的AlarmInfo实例对象 */
    public static AlarmInfo getAlarmInfo(String threadPoolName, String notifyItemType) {
        String key = buildKey(threadPoolName, notifyItemType);
        return ALARM_INFO_CACHE.get(key);
    }

    /** 获得计数器count值 */
    public static String getCount(String threadPoolName, String notifyItemType) {
        String key = buildKey(threadPoolName, notifyItemType);
        val alarmInfo = ALARM_INFO_CACHE.get(key);
        if (Objects.nonNull(alarmInfo)) return String.valueOf(alarmInfo.getCount());
        return UNKNOWN;
    }

    /** 重置lastAlarmTime和count */
    public static void reset(String threadPoolName, String notifyItemType) {
        String key = buildKey(threadPoolName, notifyItemType);
        var alarmInfo = ALARM_INFO_CACHE.get(key);
        alarmInfo.reset();
    }

    /** 警告数量+1 */
    public static void incAlarmCounter(String threadPoolName, String notifyItemType) {
        String key = buildKey(threadPoolName, notifyItemType);
        var alarmInfo = ALARM_INFO_CACHE.get(key);
        if (Objects.nonNull(alarmInfo)) alarmInfo.incCounter();
    }

    /** 获得拒绝比例、运行超时比例、队列超时比例这3个警告信息 */
    public static Triple<String, String, String> countStrRrq(String threadPoolName, ExecutorAdapter<?> executor) {
        if (!(executor instanceof DtpExecutor))
            return new ImmutableTriple<>(DEFAULT_COUNT_STR, DEFAULT_COUNT_STR, DEFAULT_COUNT_STR);

        DtpExecutor dtpExecutor = (DtpExecutor) executor;
        String rejectCount = getCount(threadPoolName, REJECT.getValue()) + " / " + dtpExecutor.getRejectCount();
        String runTimeoutCount = getCount(threadPoolName, RUN_TIMEOUT.getValue()) + " / " + dtpExecutor.getRunTimeoutCount().sum();
        String queueTimeoutCount = getCount(threadPoolName, QUEUE_TIMEOUT.getValue()) + " / " + dtpExecutor.getQueueTimeoutCount().sum();
        return new ImmutableTriple<>(rejectCount, runTimeoutCount, queueTimeoutCount);
    }

    /** 构建缓存主键key */
    private static String buildKey(String threadPoolName, String notifyItemType) {
        return threadPoolName + ":" + notifyItemType;
    }
}
